<!doctype html>

<html>
<head>
  <link rel="shortcut icon" href="static/images/favicon.ico" type="image/x-icon">
  <title>browserfeature.js (Closure Library API Documentation - JavaScript)</title>
  <link rel="stylesheet" href="static/css/base.css">
  <link rel="stylesheet" href="static/css/doc.css">
  <link rel="stylesheet" href="static/css/sidetree.css">
  <link rel="stylesheet" href="static/css/prettify.css">

  <script>
     var _staticFilePath = "static/";
     var _typeTreeName = "goog";
     var _fileTreeName = "Source";
  </script>

  <script src="static/js/doc.js">
  </script>


  <meta charset="utf8">
</head>

<body onload="grokdoc.onLoad();">

<div id="header">
  <div class="g-section g-tpl-50-50 g-split">
    <div class="g-unit g-first">
      <a id="logo" href="index.html">Closure Library API Documentation</a>
    </div>

    <div class="g-unit">
      <div class="g-c">
        <strong>Go to class or file:</strong>
        <input type="text" id="ac">
      </div>
    </div>
  </div>
</div>

<div class="clear"></div>

<h2><a href="closure_goog_editor_browserfeature.js.html">browserfeature.js</a></h2>

<pre class="prettyprint lang-js">
<a name="line1"></a>// Copyright 2005 The Closure Library Authors. All Rights Reserved.
<a name="line2"></a>//
<a name="line3"></a>// Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
<a name="line4"></a>// you may not use this file except in compliance with the License.
<a name="line5"></a>// You may obtain a copy of the License at
<a name="line6"></a>//
<a name="line7"></a>//      http://www.apache.org/licenses/LICENSE-2.0
<a name="line8"></a>//
<a name="line9"></a>// Unless required by applicable law or agreed to in writing, software
<a name="line10"></a>// distributed under the License is distributed on an &quot;AS-IS&quot; BASIS,
<a name="line11"></a>// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<a name="line12"></a>// See the License for the specific language governing permissions and
<a name="line13"></a>// limitations under the License.
<a name="line14"></a>
<a name="line15"></a>/**
<a name="line16"></a> * @fileoverview Trogedit constants for browser features and quirks that should
<a name="line17"></a> * be used by the rich text editor.
<a name="line18"></a> */
<a name="line19"></a>
<a name="line20"></a>goog.provide(&#39;goog.editor.BrowserFeature&#39;);
<a name="line21"></a>
<a name="line22"></a>goog.require(&#39;goog.editor.defines&#39;);
<a name="line23"></a>goog.require(&#39;goog.userAgent&#39;);
<a name="line24"></a>goog.require(&#39;goog.userAgent.product&#39;);
<a name="line25"></a>goog.require(&#39;goog.userAgent.product.isVersion&#39;);
<a name="line26"></a>
<a name="line27"></a>
<a name="line28"></a>/**
<a name="line29"></a> * Maps browser quirks to boolean values, detailing what the current
<a name="line30"></a> * browser supports.
<a name="line31"></a> * @type {Object}
<a name="line32"></a> */
<a name="line33"></a>goog.editor.BrowserFeature = {
<a name="line34"></a>  // Whether this browser uses the IE TextRange object.
<a name="line35"></a>  HAS_IE_RANGES: goog.userAgent.IE &amp;&amp; !goog.userAgent.isDocumentMode(9),
<a name="line36"></a>
<a name="line37"></a>  // Whether this browser uses the W3C standard Range object.
<a name="line38"></a>  // Assumes IE higher versions will be compliance with W3C standard.
<a name="line39"></a>  HAS_W3C_RANGES: goog.userAgent.GECKO || goog.userAgent.WEBKIT ||
<a name="line40"></a>      goog.userAgent.OPERA ||
<a name="line41"></a>      (goog.userAgent.IE &amp;&amp; goog.userAgent.isDocumentMode(9)),
<a name="line42"></a>
<a name="line43"></a>  // Has the contentEditable attribute, which makes nodes editable.
<a name="line44"></a>  //
<a name="line45"></a>  // NOTE(nicksantos): FF3 has contentEditable, but there are 3 major reasons
<a name="line46"></a>  // why we don&#39;t use it:
<a name="line47"></a>  // 1) In FF3, we listen for key events on the document, and we&#39;d have to
<a name="line48"></a>  //    filter them properly. See TR_Browser.USE_DOCUMENT_FOR_KEY_EVENTS.
<a name="line49"></a>  // 2) In FF3, we listen for focus/blur events on the document, which
<a name="line50"></a>  //    simply doesn&#39;t make sense in contentEditable. focus/blur
<a name="line51"></a>  //    on contentEditable elements still has some quirks, which we&#39;re
<a name="line52"></a>  //    talking to Firefox-team about.
<a name="line53"></a>  // 3) We currently use Mutation events in FF3 to detect changes,
<a name="line54"></a>  //    and these are dispatched on the document only.
<a name="line55"></a>  // If we ever hope to support FF3/contentEditable, all 3 of these issues
<a name="line56"></a>  // will need answers. Most just involve refactoring at our end.
<a name="line57"></a>  HAS_CONTENT_EDITABLE: goog.userAgent.IE || goog.userAgent.WEBKIT ||
<a name="line58"></a>      goog.userAgent.OPERA ||
<a name="line59"></a>      (goog.editor.defines.USE_CONTENTEDITABLE_IN_FIREFOX_3 &amp;&amp;
<a name="line60"></a>       goog.userAgent.GECKO &amp;&amp; goog.userAgent.isVersion(&#39;1.9&#39;)),
<a name="line61"></a>
<a name="line62"></a>  // Whether to use mutation event types to detect changes
<a name="line63"></a>  // in the field contents.
<a name="line64"></a>  USE_MUTATION_EVENTS: goog.userAgent.GECKO,
<a name="line65"></a>
<a name="line66"></a>  // Whether the browser has a functional DOMSubtreeModified event.
<a name="line67"></a>  // TODO(user): Enable for all FF3 once we&#39;re confident this event fires
<a name="line68"></a>  // reliably. Currently it&#39;s only enabled if using contentEditable in FF as
<a name="line69"></a>  // we have no other choice in that case but to use this event.
<a name="line70"></a>  HAS_DOM_SUBTREE_MODIFIED_EVENT: goog.userAgent.WEBKIT ||
<a name="line71"></a>      (goog.editor.defines.USE_CONTENTEDITABLE_IN_FIREFOX_3 &amp;&amp;
<a name="line72"></a>       goog.userAgent.GECKO &amp;&amp; goog.userAgent.isVersion(&#39;1.9&#39;)),
<a name="line73"></a>
<a name="line74"></a>  // Whether nodes can be copied from one document to another
<a name="line75"></a>  HAS_DOCUMENT_INDEPENDENT_NODES: goog.userAgent.GECKO,
<a name="line76"></a>
<a name="line77"></a>  // Whether the cursor goes before or inside the first block element on
<a name="line78"></a>  // focus, e.g., &lt;body&gt;&lt;p&gt;foo&lt;/p&gt;&lt;/body&gt;. FF will put the cursor before the
<a name="line79"></a>  // paragraph on focus, which is wrong.
<a name="line80"></a>  PUTS_CURSOR_BEFORE_FIRST_BLOCK_ELEMENT_ON_FOCUS: goog.userAgent.GECKO,
<a name="line81"></a>
<a name="line82"></a>  // Whether the selection of one frame is cleared when another frame
<a name="line83"></a>  // is focused.
<a name="line84"></a>  CLEARS_SELECTION_WHEN_FOCUS_LEAVES:
<a name="line85"></a>      goog.userAgent.IE || goog.userAgent.WEBKIT || goog.userAgent.OPERA,
<a name="line86"></a>
<a name="line87"></a>  // Whether &quot;unselectable&quot; is supported as an element style.
<a name="line88"></a>  HAS_UNSELECTABLE_STYLE: goog.userAgent.GECKO || goog.userAgent.WEBKIT,
<a name="line89"></a>
<a name="line90"></a>  // Whether this browser&#39;s &quot;FormatBlock&quot; command does not suck.
<a name="line91"></a>  FORMAT_BLOCK_WORKS_FOR_BLOCKQUOTES: goog.userAgent.GECKO ||
<a name="line92"></a>      goog.userAgent.WEBKIT || goog.userAgent.OPERA,
<a name="line93"></a>
<a name="line94"></a>  // Whether this browser&#39;s &quot;FormatBlock&quot; command may create multiple
<a name="line95"></a>  // blockquotes.
<a name="line96"></a>  CREATES_MULTIPLE_BLOCKQUOTES:
<a name="line97"></a>      (goog.userAgent.WEBKIT &amp;&amp; !goog.userAgent.isVersion(&#39;534.16&#39;)) ||
<a name="line98"></a>      goog.userAgent.OPERA,
<a name="line99"></a>
<a name="line100"></a>  // Whether this browser&#39;s &quot;FormatBlock&quot; command will wrap blockquotes
<a name="line101"></a>  // inside of divs, instead of replacing divs with blockquotes.
<a name="line102"></a>  WRAPS_BLOCKQUOTE_IN_DIVS: goog.userAgent.OPERA,
<a name="line103"></a>
<a name="line104"></a>  // Whether the readystatechange event is more reliable than load.
<a name="line105"></a>  PREFERS_READY_STATE_CHANGE_EVENT: goog.userAgent.IE,
<a name="line106"></a>
<a name="line107"></a>  // Whether hitting the tab key will fire a keypress event.
<a name="line108"></a>  // see http://www.quirksmode.org/js/keys.html
<a name="line109"></a>  TAB_FIRES_KEYPRESS: !goog.userAgent.IE,
<a name="line110"></a>
<a name="line111"></a>  // Has a standards mode quirk where width=100% doesn&#39;t do the right thing,
<a name="line112"></a>  // but width=99% does.
<a name="line113"></a>  // TODO(user|user): This should be fixable by less hacky means
<a name="line114"></a>  NEEDS_99_WIDTH_IN_STANDARDS_MODE: goog.userAgent.IE,
<a name="line115"></a>
<a name="line116"></a>  // Whether keyboard events only reliably fire on the document.
<a name="line117"></a>  // On Gecko without contentEditable, keyboard events only fire reliably on the
<a name="line118"></a>  // document element. With contentEditable, the field itself is focusable,
<a name="line119"></a>  // which means that it will fire key events. This does not apply if
<a name="line120"></a>  // application is using ContentEditableField or otherwise overriding Field
<a name="line121"></a>  // not to use an iframe.
<a name="line122"></a>  USE_DOCUMENT_FOR_KEY_EVENTS: goog.userAgent.GECKO &amp;&amp;
<a name="line123"></a>      !goog.editor.defines.USE_CONTENTEDITABLE_IN_FIREFOX_3,
<a name="line124"></a>
<a name="line125"></a>  // Whether this browser shows non-standard attributes in innerHTML.
<a name="line126"></a>  SHOWS_CUSTOM_ATTRS_IN_INNER_HTML: goog.userAgent.IE,
<a name="line127"></a>
<a name="line128"></a>  // Whether this browser shrinks empty nodes away to nothing.
<a name="line129"></a>  // (If so, we need to insert some space characters into nodes that
<a name="line130"></a>  //  shouldn&#39;t be collapsed)
<a name="line131"></a>  COLLAPSES_EMPTY_NODES:
<a name="line132"></a>      goog.userAgent.GECKO || goog.userAgent.WEBKIT || goog.userAgent.OPERA,
<a name="line133"></a>
<a name="line134"></a>  // Whether we must convert &lt;strong&gt; and &lt;em&gt; tags to &lt;b&gt;, &lt;i&gt;.
<a name="line135"></a>  CONVERT_TO_B_AND_I_TAGS: goog.userAgent.GECKO || goog.userAgent.OPERA,
<a name="line136"></a>
<a name="line137"></a>  // Whether this browser likes to tab through images in contentEditable mode,
<a name="line138"></a>  // and we like to disable this feature.
<a name="line139"></a>  TABS_THROUGH_IMAGES: goog.userAgent.IE,
<a name="line140"></a>
<a name="line141"></a>  // Whether this browser unescapes urls when you extract it from the href tag.
<a name="line142"></a>  UNESCAPES_URLS_WITHOUT_ASKING: goog.userAgent.IE &amp;&amp;
<a name="line143"></a>      !goog.userAgent.isVersion(&#39;7.0&#39;),
<a name="line144"></a>
<a name="line145"></a>  // Whether this browser supports execCommand(&quot;styleWithCSS&quot;) to toggle between
<a name="line146"></a>  // inserting html tags or inline styling for things like bold, italic, etc.
<a name="line147"></a>  HAS_STYLE_WITH_CSS:
<a name="line148"></a>      goog.userAgent.GECKO &amp;&amp; goog.userAgent.isVersion(&#39;1.8&#39;) ||
<a name="line149"></a>      goog.userAgent.WEBKIT || goog.userAgent.OPERA,
<a name="line150"></a>
<a name="line151"></a>  // Whether clicking on an editable link will take you to that site.
<a name="line152"></a>  FOLLOWS_EDITABLE_LINKS: goog.userAgent.WEBKIT ||
<a name="line153"></a>      goog.userAgent.IE &amp;&amp; goog.userAgent.isVersion(&#39;9&#39;),
<a name="line154"></a>
<a name="line155"></a>  // Whether this browser has document.activeElement available.
<a name="line156"></a>  HAS_ACTIVE_ELEMENT:
<a name="line157"></a>      goog.userAgent.IE || goog.userAgent.OPERA ||
<a name="line158"></a>      goog.userAgent.GECKO &amp;&amp; goog.userAgent.isVersion(&#39;1.9&#39;),
<a name="line159"></a>
<a name="line160"></a>  // Whether this browser supports the setCapture method on DOM elements.
<a name="line161"></a>  HAS_SET_CAPTURE: goog.userAgent.IE,
<a name="line162"></a>
<a name="line163"></a>  // Whether this browser can&#39;t set background color when the selection
<a name="line164"></a>  // is collapsed.
<a name="line165"></a>  EATS_EMPTY_BACKGROUND_COLOR: goog.userAgent.GECKO ||
<a name="line166"></a>      goog.userAgent.WEBKIT &amp;&amp; !goog.userAgent.isVersion(&#39;527&#39;),
<a name="line167"></a>
<a name="line168"></a>  // Whether this browser supports the &quot;focusin&quot; or &quot;DOMFocusIn&quot; event
<a name="line169"></a>  // consistently.
<a name="line170"></a>  // NOTE(nicksantos): FF supports DOMFocusIn, but doesn&#39;t seem to do so
<a name="line171"></a>  // consistently.
<a name="line172"></a>  SUPPORTS_FOCUSIN: goog.userAgent.IE || goog.userAgent.OPERA,
<a name="line173"></a>
<a name="line174"></a>  // Whether clicking on an image will cause the selection to move to the image.
<a name="line175"></a>  // Note: Gecko moves the selection, but it won&#39;t always go to the image.
<a name="line176"></a>  // For example, if the image is wrapped in a div, and you click on the img,
<a name="line177"></a>  // anchorNode = focusNode = div, anchorOffset = 0, focusOffset = 1, so this
<a name="line178"></a>  // is another way of &quot;selecting&quot; the image, but there are too many special
<a name="line179"></a>  // cases like this so we will do the work manually.
<a name="line180"></a>  SELECTS_IMAGES_ON_CLICK: goog.userAgent.IE || goog.userAgent.OPERA,
<a name="line181"></a>
<a name="line182"></a>  // Whether this browser moves &lt;style&gt; tags into new &lt;head&gt; elements.
<a name="line183"></a>  MOVES_STYLE_TO_HEAD: goog.userAgent.WEBKIT,
<a name="line184"></a>
<a name="line185"></a>  // Whether this browser collapses the selection in a contenteditable when the
<a name="line186"></a>  // mouse is pressed in a non-editable portion of the same frame, even if
<a name="line187"></a>  // Event.preventDefault is called. This field is deprecated and unused -- only
<a name="line188"></a>  // old versions of Opera have this bug.
<a name="line189"></a>  COLLAPSES_SELECTION_ONMOUSEDOWN: false,
<a name="line190"></a>
<a name="line191"></a>  // Whether the user can actually create a selection in this browser with the
<a name="line192"></a>  // caret in the MIDDLE of the selection by double-clicking.
<a name="line193"></a>  CARET_INSIDE_SELECTION: goog.userAgent.OPERA,
<a name="line194"></a>
<a name="line195"></a>  // Whether the browser focuses &lt;body contenteditable&gt; automatically when
<a name="line196"></a>  // the user clicks on &lt;html&gt;. This field is deprecated and unused -- only old
<a name="line197"></a>  // versions of Opera don&#39;t have this behavior.
<a name="line198"></a>  FOCUSES_EDITABLE_BODY_ON_HTML_CLICK: true,
<a name="line199"></a>
<a name="line200"></a>  // Whether to use keydown for key listening (uses keypress otherwise). Taken
<a name="line201"></a>  // from goog.events.KeyHandler.
<a name="line202"></a>  USES_KEYDOWN: goog.userAgent.IE ||
<a name="line203"></a>      goog.userAgent.WEBKIT &amp;&amp; goog.userAgent.isVersion(&#39;525&#39;),
<a name="line204"></a>
<a name="line205"></a>  // Whether this browser converts spaces to non-breaking spaces when calling
<a name="line206"></a>  // execCommand&#39;s RemoveFormat.
<a name="line207"></a>  // See: https://bugs.webkit.org/show_bug.cgi?id=14062
<a name="line208"></a>  ADDS_NBSPS_IN_REMOVE_FORMAT:
<a name="line209"></a>      goog.userAgent.WEBKIT &amp;&amp; !goog.userAgent.isVersion(&#39;531&#39;),
<a name="line210"></a>
<a name="line211"></a>  // Whether the browser will get stuck inside a link.  That is, if your cursor
<a name="line212"></a>  // is after a link and you type, does your text go inside the link tag.
<a name="line213"></a>  // Bug: http://bugs.webkit.org/show_bug.cgi?id=17697
<a name="line214"></a>  GETS_STUCK_IN_LINKS:
<a name="line215"></a>      goog.userAgent.WEBKIT &amp;&amp; !goog.userAgent.isVersion(&#39;528&#39;),
<a name="line216"></a>
<a name="line217"></a>  // Whether the browser corrupts empty text nodes in Node#normalize,
<a name="line218"></a>  // removing them from the Document instead of merging them.
<a name="line219"></a>  NORMALIZE_CORRUPTS_EMPTY_TEXT_NODES: goog.userAgent.GECKO &amp;&amp;
<a name="line220"></a>      goog.userAgent.isVersion(&#39;1.9&#39;) || goog.userAgent.IE ||
<a name="line221"></a>      goog.userAgent.OPERA ||
<a name="line222"></a>      goog.userAgent.WEBKIT &amp;&amp; goog.userAgent.isVersion(&#39;531&#39;),
<a name="line223"></a>
<a name="line224"></a>  // Whether the browser corrupts all text nodes in Node#normalize,
<a name="line225"></a>  // removing them from the Document instead of merging them.
<a name="line226"></a>  NORMALIZE_CORRUPTS_ALL_TEXT_NODES: goog.userAgent.IE,
<a name="line227"></a>
<a name="line228"></a>  // Browsers where executing subscript then superscript (or vv) will cause both
<a name="line229"></a>  // to be applied in a nested fashion instead of the first being overwritten by
<a name="line230"></a>  // the second.
<a name="line231"></a>  NESTS_SUBSCRIPT_SUPERSCRIPT: goog.userAgent.IE || goog.userAgent.GECKO ||
<a name="line232"></a>      goog.userAgent.OPERA,
<a name="line233"></a>
<a name="line234"></a>  // Whether this browser can place a cursor in an empty element natively.
<a name="line235"></a>  CAN_SELECT_EMPTY_ELEMENT: !goog.userAgent.IE &amp;&amp; !goog.userAgent.WEBKIT,
<a name="line236"></a>
<a name="line237"></a>  FORGETS_FORMATTING_WHEN_LISTIFYING: goog.userAgent.GECKO ||
<a name="line238"></a>      goog.userAgent.WEBKIT &amp;&amp; !goog.userAgent.isVersion(&#39;526&#39;),
<a name="line239"></a>
<a name="line240"></a>  LEAVES_P_WHEN_REMOVING_LISTS: goog.userAgent.IE || goog.userAgent.OPERA,
<a name="line241"></a>
<a name="line242"></a>  CAN_LISTIFY_BR: !goog.userAgent.IE &amp;&amp; !goog.userAgent.OPERA,
<a name="line243"></a>
<a name="line244"></a>  // See bug 1286408. When somewhere inside your selection there is an element
<a name="line245"></a>  // with a style attribute that sets the font size, if you change the font
<a name="line246"></a>  // size, the browser creates a font tag, but the font size in the style attr
<a name="line247"></a>  // overrides the font tag. Only webkit removes that font size from the style
<a name="line248"></a>  // attr.
<a name="line249"></a>  DOESNT_OVERRIDE_FONT_SIZE_IN_STYLE_ATTR: !goog.userAgent.WEBKIT,
<a name="line250"></a>
<a name="line251"></a>  // Implements this spec about dragging files from the filesystem to the
<a name="line252"></a>  // browser: http://www.whatwg/org/specs/web-apps/current-work/#dnd
<a name="line253"></a>  SUPPORTS_HTML5_FILE_DRAGGING: (goog.userAgent.product.CHROME &amp;&amp;
<a name="line254"></a>                                 goog.userAgent.product.isVersion(&#39;4&#39;)) ||
<a name="line255"></a>      (goog.userAgent.product.SAFARI &amp;&amp; goog.userAgent.isVersion(&#39;533&#39;)) ||
<a name="line256"></a>      (goog.userAgent.GECKO &amp;&amp; goog.userAgent.isVersion(&#39;2.0&#39;)) ||
<a name="line257"></a>      (goog.userAgent.IE &amp;&amp; goog.userAgent.isVersion(&#39;10&#39;)),
<a name="line258"></a>
<a name="line259"></a>  // Version of Opera that supports the opera-defaultBlock execCommand to change
<a name="line260"></a>  // the default block inserted when [return] is pressed. Note that this only is
<a name="line261"></a>  // used if the caret is not already in a block that can be repeated.
<a name="line262"></a>  // TODO(user): Link to public documentation of this feature if Opera puts
<a name="line263"></a>  // something up about it.
<a name="line264"></a>  SUPPORTS_OPERA_DEFAULTBLOCK_COMMAND:
<a name="line265"></a>      goog.userAgent.OPERA &amp;&amp; goog.userAgent.isVersion(&#39;11.10&#39;),
<a name="line266"></a>
<a name="line267"></a>  SUPPORTS_FILE_PASTING: goog.userAgent.product.CHROME &amp;&amp;
<a name="line268"></a>      goog.userAgent.product.isVersion(&#39;12&#39;)
<a name="line269"></a>};
</pre>


</body>
</html>
